import { useState, useEffect, useRef } from "react";
import { MarkdownRenderer } from "react-markdown-renderer-integration";

// 打字机组件接收的属性
interface TypewriterProps {
  /**
   * 要显示的文本内容
   */
  content: string;

  /**
   * 是否为Markdown格式
   * @default false
   */
  isMarkdown?: boolean;

  /**
   * 打字速度(字符/秒)
   * @default 30
   */
  speed?: number;

  /**
   * 允许的最小打字延迟(毫秒)
   * @default 5
   */
  minDelay?: number;

  /**
   * 允许的最大打字延迟(毫秒)
   * @default 30
   */
  maxDelay?: number;

  /**
   * 是否已完成打字
   * @default false
   */
  completed?: boolean;

  /**
   * 打字完成时的回调
   */
  onComplete?: () => void;

  /**
   * 是否允许HTML渲染(仅在isMarkdown为true时有效)
   * @default false
   */
  allowHtml?: boolean;

  /**
   * 自定义CSS类名
   */
  className?: string;

  /**
   * 自定义打字容器样式
   */
  containerClassName?: string;

  /**
   * 是否显示光标
   * @default true
   */
  showCursor?: boolean;

  /**
   * 光标样式
   * @default "text-blue-500"
   */
  cursorClassName?: string;
}

/**
 * Typewriter 打字机组件
 *
 * 高度还原ChatGPT打字效果的组件，支持逐字显示文本，
 * 支持Markdown内容的渲染，可以自定义打字速度和延迟。
 */
const Typewriter = ({
  content,
  isMarkdown = false,
  speed = 300,
  minDelay = 5,
  maxDelay = 30,
  completed = false,
  onComplete,
  allowHtml = false,
  className = "",
  containerClassName = "",
  showCursor = true,
  cursorClassName = "text-blue-500",
}: TypewriterProps) => {
  // 当前显示的文本内容
  const [displayedContent, setDisplayedContent] = useState<string>("");
  // 是否已完成打字
  const [isCompleted, setIsCompleted] = useState<boolean>(completed);
  // 是否暂停打字
  const [isPaused, setIsPaused] = useState<boolean>(false);
  // 用于存储动画帧标识符
  const animationFrameRef = useRef<number | null>(null);
  // 用于存储上次更新时间
  const lastUpdateTimeRef = useRef<number>(0);
  // 当前字符索引
  const indexRef = useRef<number>(0);

  // 根据speed计算延迟时间(毫秒)
  const calculateDelay = () => {
    // 基础延迟时间
    const baseDelay = 1000 / speed;
    // 添加一些随机性，使打字效果更自然
    const randomFactor = Math.random() * (maxDelay - minDelay) + minDelay;
    return baseDelay + randomFactor;
  };

  // 打字动画函数
  const typeText = (timestamp: number) => {
    // 如果是暂停状态，继续请求下一帧但不做任何操作
    if (isPaused) {
      animationFrameRef.current = requestAnimationFrame(typeText);
      return;
    }

    // 如果是第一次更新或者时间间隔已达到预设延迟
    if (
      lastUpdateTimeRef.current === 0 ||
      timestamp - lastUpdateTimeRef.current > calculateDelay()
    ) {
      // 更新最后更新时间
      lastUpdateTimeRef.current = timestamp;

      // 检查是否已经完成打字
      if (indexRef.current < content.length) {
        // 更新显示内容
        setDisplayedContent(content.substring(0, indexRef.current + 1));
        // 增加索引
        indexRef.current++;
      } else {
        // 完成打字
        setIsCompleted(true);
        // 如果提供了完成回调，则调用
        if (onComplete) {
          onComplete();
        }
        return;
      }
    }

    // 如果未完成打字，继续请求下一帧
    if (indexRef.current < content.length) {
      animationFrameRef.current = requestAnimationFrame(typeText);
    }
  };

  // 监控content变化，重置并开始新的打字动画
  useEffect(() => {
    // 重置状态
    setDisplayedContent("");
    setIsCompleted(completed);
    setIsPaused(false);
    indexRef.current = 0;
    lastUpdateTimeRef.current = 0;

    // 如果内容为空或已完成，直接显示全部内容
    if (!content || completed) {
      setDisplayedContent(content);
      setIsCompleted(true);
      if (onComplete) {
        onComplete();
      }
      return;
    }

    // 开始打字动画
    animationFrameRef.current = requestAnimationFrame(typeText);

    // 清理函数，取消动画帧
    return () => {
      if (animationFrameRef.current !== null) {
        cancelAnimationFrame(animationFrameRef.current);
      }
    };
  }, [content, completed]);

  // 暂停/继续打字动画的方法
  const togglePause = () => {
    setIsPaused((prev) => {
      const newState = !prev;
      // 如果从暂停状态恢复，重新开始动画
      if (newState === false && !isCompleted) {
        animationFrameRef.current = requestAnimationFrame(typeText);
      }

      return newState;
    });
  };

  // 渲染内容
  const renderContent = () => {
    if (isMarkdown) {
      return (
        <MarkdownRenderer
          content={displayedContent}
          allowHtml={allowHtml}
          className={className}
        />
      );
    }

    return <p className={className}>{displayedContent}</p>;
  };

  // 闪烁的光标组件
  const Cursor = () => (
    <span
      className={`inline-block w-[2px] h-[14px] ml-[1px] mb-[2px] animate-blink ${cursorClassName}`}
    />
  );

  return (
    <div
      className={`typewriter ${containerClassName}`}
      onClick={!isCompleted ? togglePause : undefined}
    >
      {renderContent()}
      {showCursor && !isCompleted && <Cursor />}
    </div>
  );
};

export default Typewriter;
